﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using ClassDAL;
using ClassDAL.Entities;
using ClassDAL.Models;
using CodeGenBL.Dto;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using ProjectDAL.Models;

namespace CodeGenBL
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "CodeGenBL" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select CodeGenBL.svc or CodeGenBL.svc.cs at the Solution Explorer and start debugging.
    public class CodeGenBL : ICodeGenBL
    {
        public ISession Session;
        ISessionFactory SessionFactory;

        public CodeGenBL()
        {
            System.Configuration.AppSettingsReader appReader = new System.Configuration.AppSettingsReader();
            string connectionString = Convert.ToString(appReader.GetValue("connectionString", typeof(string)));
            string mappingScriptPath = AppDomain.CurrentDomain.BaseDirectory + "/db_mappings";
            if (!Directory.Exists(mappingScriptPath))
                Directory.CreateDirectory(mappingScriptPath);

            SessionFactory = Fluently.Configure()
                .Database(
                    MsSqlConfiguration.MsSql2008
                    .ConnectionString(@connectionString))
                    .Mappings(x => x.AutoMappings.Add(AutoMap.AssemblyOf<ClassModel>().Where(t => t.Namespace.EndsWith("Entities"))).ExportTo(@mappingScriptPath))
                    //.ExposeConfiguration(BuildSchema) // ********** ใช้ครั้งแรกเท่านั้น (กรณียังไม่มี Table)
                    .BuildSessionFactory();
            Session = SessionFactory.OpenSession();
        }
        private static void BuildSchema(Configuration config)
        {
            new SchemaExport(config).Create(false, true);
        }

        public ActionResultDto<int> AddClass(ClassModelDto classModelDto)
        {
            ActionResultDto<int> result = new ActionResultDto<int>();
            using (Session.BeginTransaction())
            {
                try
                {
                    var classModel = classModelDto.TransformToClassModel();
                    IClassDAL obj = new ClassDAL.ClassDAL(Session);
                    result.Data = obj.AddClass(classModel);
                    Session.Transaction.Commit();

                    result.Status = true;
                }
                catch (Exception ex)
                {
                    Session.Transaction.Rollback();
                    result.Status = false;
                    result.ErrorMessage = ex.Message;
                }
            }

            return result;
        }

        public ActionResultDto<List<ClassHeaderDto>> GetClassByProjectId(ProjectPKDto projectPKDto)
        {
            ActionResultDto<List<ClassHeaderDto>> result = new ActionResultDto<List<ClassHeaderDto>>();
            try
            {
                IClassDAL obj = new ClassDAL.ClassDAL(Session);
                ClassSearchCriteria search = null;
                if (projectPKDto != null)
                {
                    search = new ClassSearchCriteria()
                    {
                        ProjectId = projectPKDto.ProjectId


                    };
                }

                var clsdal = obj.GetClass(search);
                if (clsdal.Count > 0)
                {
                    result.Data = new List<ClassHeaderDto>();
                    foreach (var item in clsdal)
                    {
                        result.Data.Add(new ClassHeaderDto()
                        {
                            Id = item.Id,
                            name = item.Name

                        });
                    }
                }
                result.Status = true;
            }
            catch (Exception ex)
            {
                result.Status = false;
                result.ErrorMessage = ex.Message;
            }
            return result;
        }

        public ActionResultDto<ClassModelDto> GetClass(ClassPkDto classPkDto)
        {
            // implements by P'Coke
            var result = new ActionResultDto<ClassModelDto>();
            if (classPkDto == null) return result;

            try
            {
                IClassDAL obj = new ClassDAL.ClassDAL(Session);
                var criteria = new ClassSearchCriteria { Id = classPkDto.ClassId };
                var clsdto = obj.GetClass(criteria);
                if (clsdto != null && clsdto.Count > 0)
                {
                    Microsoft.CSharp.CSharpCodeProvider prov = new Microsoft.CSharp.CSharpCodeProvider();
                    if (!prov.IsValidIdentifier(clsdto[0].Name))
                    {
                        throw new Exception("Invalid Charecters");
                    }
                    result.Data = new ClassModelDto();
                    result.Data.Id = clsdto[0].Id;
                    result.Data.Name = clsdto[0].Name;
                    result.Data.ProjectId = clsdto[0].ProjectId;

                    if (clsdto[0].Attributes!=null)
                    {
                        result.Data.Attributes = new List<AttributeModelDto>();
                        foreach (var item in clsdto[0].Attributes)
                        {
                            if (!prov.IsValidIdentifier(item.Name))
                            {
                                throw new Exception("Invalid Charecters");
                            }
                            result.Data.Attributes.Add(new AttributeModelDto
                            {
                                AutoKey = item.AutoKey,
                                DataType = item.DataType,
                                Display = item.Display,
                                FieldDescription = item.FieldDescription,
                                FieldType = item.FieldType,
                                Id = item.Id,
                                Label = item.Label,
                                Length = item.Length,
                                Name = item.Name,
                                Nullable = item.Nullable,
                                Pk = item.Pk,
                                Search = item.Search,
                                SearchResult = item.SearchResult,
                                SeqNo = item.SeqNo,
                                DisplayLengthInGrid = item.DisplayLengthInGrid
                            });
                        }
                    }

                    result.Status = true;
                }

            }
            catch (Exception ex)
            {
                result.Status = false;
                result.ErrorMessage = ex.Message;
            }

            return result;
        }
    }
}
